/*
 * Copyright 2009 Jesse McLaughlin (nzjess@gmail.com)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *         http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.travelfusion.xmlclient;

import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.travelfusion.xmlclient.exception.TfXClientException;
import org.travelfusion.xmlclient.xobject.XRequest;
import org.travelfusion.xmlclient.xobject.XResponse;

/**
 * This is the central interface for sending and receiving commands to and from the TRAVELfusion TripPlannerXML service.
 * <p>
 * The TripPlannerXML service is an XML over HTTP web-service that allows callers to search for travel offers (eg.
 * flights, hotels, car rentals, package deals, trains, ferries, etc.) from a multitude of online suppliers. Refer to
 * the <a href="https://whitelabels.travelfusion.com/xmlspec/v2/detailedspec/index.php">specification</a> for details on
 * the API offered by this service.
 * <p>
 * Note that you have to register and obtain an XML Login ID before using the online web-service. Please see here: <a
 * href="https://whitelabels.travelfusion.com/registration/">https://whitelabels.travelfusion.com/registration/</a>
 * <p>
 * This interface defines just one method: {@link #invoke(XRequest)}. This method takes a single parameter, the request
 * to send, and returns the response received. At this level, requests and responses are typed as abstract
 * {@link XRequest} and {@link XResponse} instances respectively. Hence, callers must cast the returned value based on
 * the value passed in as the request.
 * <p>
 * In other words, implementations of this interface are responsible for somehow translating a request object into XML,
 * passing this XML to the TripPlanner service, receiving the XML response, and then creating an appropriate response
 * object to return to the caller.
 * <p>
 * By design, the main intent of this interface is to free the caller from any knowledge of the XML nature of the
 * underlying service. However, it also remains completely agnostic of the actual commands that may be sent. That is,
 * this interface in no way attempts to statically bind individual TripPlannerXML commands to different Java methods.
 * Rather it does the complete opposite, whereby a single 'invoke' method is responsble for dynamically interpreting the
 * requested command, and producing the response. For instance, implementations may well rely on the runtime type of the
 * request object passed in to produce the required dynamic invocation behaviour.
 * <p>
 * Of course, higher level abstractions may be created on top of this facility in order to provide statically typed
 * command/method bindings. However, that concern falls outside the scope of this interface itself.
 * 
 * @author Jesse McLaughlin (nzjess@gmail.com)
 * @author Ana Henneberke (ana.henneberke@gmail.com)
 */
public interface TfXClient {

  /**
   * Subclasses should annotate their implementation of {@link TfXClient#invoke(XRequest)} with this annotation, to
   * support Guice interceptor bindings.
   */
  @Target(ElementType.METHOD)
  @Retention(RetentionPolicy.RUNTIME)
  public static @interface Invoke {}

  /**
   * Invokes the TRAVELfusion XML service, sending the given request and returning the received response. The
   * {@link XRequest} and {@link XResponse} instances are abstract at this level. The caller is responsible for
   * providing an instance that can be meaningfully handled by this client instance, and for interpreting (ie. casting)
   * the corresponding response that is returned.
   * 
   * @see XRequest
   * @see XResponse
   * 
   * @param request The request to send.
   * 
   * @throws TfXClientException if something goes wrong invoking the service. Depending on what went wrong, the
   *           exception may be some subclass that contains more detail on the nature of the problem that occurred.
   * @throws IOException if the underlying transport throws an I/O exception.
   * 
   * @return The response received. This must be cast by the caller to the appropriate type based on what was passed in
   *         as the request. This may require some knowledge on the part of the caller of the actual client
   *         implementation.
   */
  XResponse invoke(XRequest request) throws TfXClientException, IOException;

  /**
   * Invokes the TRAVELfusion XML service, sending the given request and returning the received response, ignoring any
   * response that might already be stored in any caching mechanism the implementing class might use, which means this
   * method will always call the TRAVELfusion XML service directly. {@link XRequest} and {@link XResponse} instances are
   * abstract at this level. The caller is responsible for providing an instance that can be meaningfully handled by
   * this client instance, and for interpreting (ie. casting) the corresponding response that is returned.
   * 
   * @see XRequest
   * @see XResponse
   * 
   * @param request The request to send.
   * 
   * @throws TfXClientException if something goes wrong invoking the service. Depending on what went wrong, the
   *           exception may be some subclass that contains more detail on the nature of the problem that occurred.
   * @throws IOException if the underlying transport throws an I/O exception.
   * 
   * @return The response received. This must be cast by the caller to the appropriate type based on what was passed in
   *         as the request. This may require some knowledge on the part of the caller of the actual client
   *         implementation.
   */
  XResponse invokeIgnoreCache(XRequest request) throws TfXClientException, IOException;

}
